package serialStudy;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author mac
 * @date 2021/9/1 6:47 下午
 */
public class ShallowCopyTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        CollectionCloneOperation.zileishixianxuliehua();
    }
}

/**
 * 集合克隆操作类
 */
class CollectionCloneOperation {
    private static List<Integer> list;

    static {
        list = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            list.add(i);
        }
    }

    /**
     * 数组深拷贝
     */
    public static void deepCopyOfList() throws IOException, ClassNotFoundException {
        //对对象序列化，先转成字符流再转换成字节流
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream);
        outputStream.writeObject(list);
        //对对象反序列化，获取字节数组转成字节输入流，再转成字符输入流
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        List<Integer> o = (List<Integer>)objectInputStream.readObject();
        System.out.println(o.equals(list));
    }

    /**
     * 验证类定义发生变化之后能否序列化
     */
    public static void xuliehuabuyizhi() throws IOException {
        CoCo coCo = new CoCo("白华国",19.00);
        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(new File("类结构发生变化然后进行反序列化.txt")));
        outputStream.writeObject(coCo);
    }

    /**
     * 类定义发生变化进行反序列化操作
     */
    public static void deserialzableTest() throws IOException, ClassNotFoundException {
        ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(new File("类结构发生变化然后进行反序列化.txt")));
        CoCo coCo = (CoCo) objectInputStream.readObject();
        System.out.println("coCo = " + coCo);
    }

    /**
     * 子类实现了序列化接口但是父类没有实现
     */
    public static void zileishixianxuliehua() throws IOException, ClassNotFoundException {
        //子类实现序列化接口，父类没有实现的情况

        SubClass1 subClass1 = new SubClass1();
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream outputStream = new ObjectOutputStream(byteArrayOutputStream);
        outputStream.writeObject(subClass1);
        outputStream.close();

        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
        Object o = objectInputStream.readObject();
        System.out.println("o = " + o);
        objectInputStream.close();

        //父类实现序列化接口的情况
        SubClass2 subClass2 = new SubClass2();
        ByteArrayOutputStream byteArrayOutputStream1 = new ByteArrayOutputStream();
        ObjectOutputStream outputStream1 = new ObjectOutputStream(byteArrayOutputStream1);
        outputStream1.writeObject(subClass2);

        ByteArrayInputStream byteArrayInputStream1 = new ByteArrayInputStream(byteArrayOutputStream1.toByteArray());
        ObjectInputStream objectInputStream1 = new ObjectInputStream(byteArrayInputStream1);
        Object o1 = objectInputStream1.readObject();
        System.out.println("o1 = " + o1);
    }
}

class MyResources implements Serializable{

    private static final long serialVersionUID = 4703642791901699791L;

    public static String address;

    static {
        address = "双子座大厦";
    }

    String name;

     int age;

    public MyResources() {
    }

    public MyResources(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public static String getAddress() {
        return address;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public static void setAddress(String address) {
        MyResources.address = address;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 序列化时调用的方法----当属性被transient修饰之后，通过该方法还能将属性序列化
     * @param outputStream
     * @throws IOException
     */
    private void writeObject(ObjectOutputStream outputStream) throws IOException{

    }

    /**
     * 该方法同上
     * @param inputStream
     * @throws IOException
     */
    private void readObject(ObjectInputStream inputStream) throws IOException{

    }

    /**
     * 当子类在继承之前已经实现了序列化，但是之后继承结构发生变化，反序列化时需要父类中的属性要有默认值
     *
     * 这个方法就是设置默认值的方法
     * @throws IOException
     */
    private void readObjectNoData() throws IOException{
        this.age = 10;
        this.name = "东临碣石，以观沧海";
    }

    @Override
    public String toString() {
        return "MyResources{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

class CoCo extends MyResources implements Serializable{

    private static final long serialVersionUID = -7169065857775534881L;

    public CoCo() {
    }

    public CoCo(String menu, Double price) {
        this.menu = menu;
        this.price = price;
    }

    private String menu;

    private Double price;

    public String getMenu() {
        return menu;
    }

    public Double getPrice() {
        return price;
    }

    public void setMenu(String menu) {
        this.menu = menu;
    }

    public void setPrice(Double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "CoCo{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", menu='" + menu + '\'' +
                ", price=" + price +
                '}';
    }
}

/**
 * 实现该接口的类只能手动序列化无法自动序列化
 *
 *
 */
class ExternalClass implements Externalizable{
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {

    }

    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {

    }
}

/**
 * ---如何在不破坏父类的前提下，让子类无法序列化
 * 父类
 */
class SuperClass implements Serializable{

}

/**
 * 子类--在不修改父类的前提下无法让子类序列化
 */
class SubClass extends SuperClass{
    private void writeObject(ObjectOutputStream outputStream) throws IOException{
        throw new NotSerializableException("XXX");
    }
    private void readObject(ObjectInputStream inputStream)throws IOException, ClassNotFoundException{
        throw new NotSerializableException("XXX");
    }
    private void readObjectNoData() throws ObjectStreamException{
        throw new NotSerializableException("XXX");
    }
}

/**
 * 子类实现序列化接口 父类不实现
 * 探讨的问题：   父子类都会序列化么？
 *              序列化的时候会存在什么问题？
 *              父子类构造器的调用顺序是什么？
 *
 *
 */
class SuperClass1{
    Integer age;
    public SuperClass1(){
        System.out.println("子类实现了序列化接口的父类构造器");
    }
}

class SubClass1 extends SuperClass1 implements Serializable{
    private static final long serialVersionUID = -1710114683334444936L;
    String name;

    public SubClass1() {
        System.out.println("子类实现了序列化接口的子类构造器");
    }
}

/**
 * 父类实现序列化接口，子类自动实现序列化无需显式实现序列化接口
 */
class Super2 implements Serializable{
    private static final long serialVersionUID = 6159364146060859030L;

    public Super2() {
        System.out.println("父类实现了序列化接口的父类构造器");
    }
}

class SubClass2 extends Super2{

    private static final long serialVersionUID = 7257499177470146678L;

    public SubClass2() {
        System.out.println("父类实现了序列化接口的子类构造器");
    }
}
